import moment from "moment";
import { Request, Response } from "express";
import { fn, col, literal, Op, WhereOptions } from "sequelize";
import { EventLog, EventLast } from "../db";
import { checkAuthorization, getUserId } from "./util";

function dateFormat(date: string | Date) {
  const newDate =
    typeof date === "string" ? new Date(date.replace(/-/g, "/")) : date;
  return moment(newDate);
}

export default {
  "GET /api/event-log/list": async (req: Request, res: Response) => {
    if (checkAuthorization(req, res)) return;
    const UserId = getUserId(req, res);
    if (!UserId) return;
    const { current, pageSize } = req.query as any;
    const query = JSON.parse(req.query.query as any);
    const where: WhereOptions = { UserId };

    if (query.startAt) {
      // 2022-5-5
      const startAt = dateFormat(query.startAt);

      where.startAt = {
        [Op.gte]: startAt.toDate(), // 2022/5/5 <= startAt
        [Op.lt]: startAt.add(1, "day").toDate(), // startAt < 2022/5/6
      };
    }

    const total = await EventLog.count({ where });
    const rows = await EventLog.findAll({
      where,
      offset: parseInt(`${(current - 1) * pageSize}`) || 0,
      limit: parseInt(pageSize) || 20,
      order: [["startAt", "DESC"]],
    });
    res.send({
      success: true,
      total,
      data: rows,
    });
  },
  "GET /api/event-log/month": async (req: Request, res: Response) => {
    if (checkAuthorization(req, res)) return;
    const UserId = getUserId(req, res);
    if (!UserId) return;
    const month: string = req.query.month as any;
    const startAt = moment(dateFormat(month).format("YYYY-MM-01 00:00:00"));
    console.log("[month] startAt: "+startAt.format("YYYY-MM-DD HH:mm:ss"));
    
    const rows = await EventLog.findAll({
      attributes: [
        [fn("DATE_FORMAT", col("startAt"), "%Y/%c/%e"), "date"],
        [fn("COUNT", col("*")), "total"],
      ],
      group: col("date"),
      order: [[col("date"), "asc"]],
      where: {
        UserId,
        startAt: {
          [Op.gte]: startAt.toDate(), // 2022/5/1 <= startAt
          [Op.lt]: startAt.add(1, "month").toDate(), // startAt < 2022/6/1
        },
      },
    });
    res.send({
      success: true,
      data: rows,
    });
  },
  "GET /api/event-log/stat": async (req: Request, res: Response) => {
    if (checkAuthorization(req, res)) return;
    const UserId = getUserId(req, res);
    if (!UserId) return;
    const { startAt, endAt } = req.query as any;
    const rows = await EventLog.findAll({
      attributes: [
        "name",
        [fn("ANY_VALUE", col("icon")), "icon"],
        [fn("ANY_VALUE", col("color")), "color"],
        [
          fn(
            "SUM",
            fn(
              "TIMESTAMPDIFF",
              literal("SECOND"),
              col("startAt"),
              fn("IFNULL", col("endAt"), new Date())
            )
          ),
          "total",
        ],
      ],
      where: {
        UserId,
        startAt: {
          [Op.gte]: startAt,
          [Op.lt]: endAt,
        },
      },
      group: col("name"),
      order: [[col("total"), "DESC"]],
    });
    const list: any[] = JSON.parse(JSON.stringify(rows));
    if (!list.length) {
      res.send({
        success: true,
        data: [],
      });
      return;
    }
    const total = list.reduce((p, c) => {
      p += parseFloat((parseInt(c.total) / 1000).toFixed(3));
      return p;
    }, 0);
    const items = list.map((item) => {
      const count = parseFloat((parseInt(item.total) / 1000).toFixed(3));
      const value = Math.round((count / total) * 100);
      return { ...item, value };
    });
    let difference = items.reduce((p, c) => {
      p += c.value;
      return p;
    }, 0);
    difference -= 100;

    items[0].value -= difference;

    res.send({
      success: true,
      data: items,
    });
  },
  // 修改某个log
  "PUT /api/event-log": async (req: Request, res: Response) => {
    if (checkAuthorization(req, res)) return;
    const { id, name, icon, color } = req.body;
    const log = await EventLog.findOne({ where: { id } });
    if (!log) {
      res.send({
        success: false,
        data: null,
        errorCode: "700",
        errorMessage: "该事件不存在！",
      });
      return;
    }
    await EventLog.update({ name, icon, color }, { where: { id } });
    res.send({
      success: true,
      data: id,
    });
  },
  // 新增一个log
  "POST /api/event-log": async (req: Request, res: Response) => {
    if (checkAuthorization(req, res)) return;
    const UserId = getUserId(req, res);
    if (!UserId) return;
    const { name, icon, color } = req.body;
    console.log("POST /api/event-log ", req.body);
    let last = await EventLast.findOne({ where: { UserId } });
    const log = await EventLog.create({ name, icon, color, UserId });
    if (last) {
      const now = moment();
      const lastLog = await EventLog.findOne({
        where: { id: last.get("EventLogId") as string },
      });
      const startAt = moment(lastLog.get("startAt"));

      if (startAt.format("YYYY-MM-DD") === now.format("YYYY-MM-DD")) {
        await EventLog.update(
          { endAt: now.toDate() },
          { where: { id: last.get("EventLogId") as string } }
        );
      } else {
        await EventLog.update(
          { endAt: startAt.format("YYYY-MM-DD 23:59:59") },
          { where: { id: last.get("EventLogId") as string } }
        );
        await EventLog.create({
          name: lastLog.get("name"),
          icon: lastLog.get("icon"),
          color: lastLog.get("color"),
          startAt: now.format("YYYY-MM-DD 00:00:00"),
          endAt: now.toDate(),
          UserId,
        });
      }
      await last.destroy();
    }
    await EventLast.create({ UserId, EventLogId: log.get("id") });
    res.send({
      success: true,
      data: log.get("id"),
    });
  },
};
